home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
p063b9s.zip
/
UNIT
/
NODELIST.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-03-02
|
43KB
|
1,216 lines
UNIT NodeList;
{╔══════════════════════════════════════════════════════════════════════════╗}
{║ Read/Write nodelist for QBBS/V6/RA/SBBS/V7 Last changed: 02.03.97 SA ║}
{║ ║}
{║ (C) Copyright 1989-97 by ║}
{║ Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager ║}
{║ ║}
{║ This source may not be given to anybody, without the written permission ║}
{║ from The Portal Team. ║}
{╚══════════════════════════════════════════════════════════════════════════╝}
{$I POPDEFS.INC}
INTERFACE
USES Use32, Dos, OpLArray, PoPTypes;
CONST
nlf_CrashMail = 16;
nlf_HubNode = 4096;
NodeListPathStr : String[67]='';
TYPE
{ Nodelist Records ******************************************* }
QBBSNodeTypes = (ntZone, ntRegion, ntNet, ntNode);
QBBSNodeIdxRecord = record
NodeType : QBBSNodeTypes;
Number,
Cost : SmallWord;
RawFile : Byte;
RawPos : LongInt;
end;
NewNodeList =RECORD
NetNumber,
NodeNumber : SmallInt;
Cost : SmallWord;
SystemName : ARRAY[1..34] OF Char;
PhoneNumber : ARRAY[1..40] OF Char;
MiscInfo : ARRAY[1..30] OF Char;
Password : ARRAY[1..8] OF Char;
RealCost : SmallWord;
HubNode : SmallInt; { or Point if Bit 12 set in NodeFlags }
BaudRate : Byte;
ModemType : Byte;
NodeFlags : SmallWord;
NodeFiller : SmallWord;
END;
NewNodeListIndex=RECORD
Node : SmallInt;
Net : SmallInt;
END;
NodeExtra=RECORD
Name : s12;
Time : LongInt;
END;
VirtualIndexType=RECORD
Zone,
Net,
Node : SmallInt;
END;
NodeListRecType=RECORD
NodeType : Byte; { QuickBBS }
Adr : TFidoAddress;
Cost : SmallWord;
SystemName : String[34];
PhoneNumber : String[40];
MiscInfo : String[30];
SysopName : String[30];
Password : String[8];
RealCost : SmallWord;
HubNode : SmallInt; { or Point if Bit 12 in Flags set }
BaudRate : SmallWord; (* Byte *)
ModemType : Byte;
Flags : SmallWord;
END;
CONST
TranslationTable : Pointer = NIL;
CurrentCostTable : Pointer = NIL;
VAR
NodeListIndex : OpArray;
NodeListIndexNum : Word;
NodeListEntry : NodeListRecType;
NodePos : LongInt;
CurrentTextFileNumber : Byte;
CurrentTranslatCount : WORD;
CurrentGeneralCost,
CurrentCostCount : WORD;
{-------------------------------------------------------------------------}
{ Call with Zone, Net, Node of the Board you want to find in the }
{ nodelist, returns True if the board is found. }
{ The NlPath MUST end with a '\', and contain no filename (only the }
{ path). }
{ The board info is returned in NListRec (see definition above). }
{-------------------------------------------------------------------------}
PROCEDURE DisplaySingleNode(CONST Address: TFidoAddress);
PROCEDURE InitialiseNodelist(CONST NlPath: PathStr; NLType: NodeListType);
PROCEDURE DeAllocateNodeListIndex;
FUNCTION FindFirstNode(VAR NListRec: NodeListRecType) : Boolean;
FUNCTION FindNextNode(VAR NListRec: NodeListRecType) : Boolean;
FUNCTION FindPreviousNode(VAR NListRec: NodeListRecType) : Boolean;
FUNCTION FindNode(CONST Address: TFidoAddress; VAR NlistRecZ: NodeListRecType): Boolean;
FUNCTION WriteNode(CONST NListRec: NodeListRecType): Boolean;
PROCEDURE ReadTranslationTable(Silent: Boolean);
FUNCTION PhoneTranslation(ph: S60): S60;
PROCEDURE GetSpecialModemInfo(CONST s: STRING; VAR mt: Byte; VAR br: SmallWord);
FUNCTION ListExtension(CONST FName: S12): S12;
FUNCTION ReadCostTable(Silent: Boolean): Boolean;
FUNCTION FindCost(CONST Phone: S60): WORD;
FUNCTION GetSysOpName(CONST Adr: TFidoAddress): S40;
IMPLEMENTATION
USES OpCrt, OpWindow, OpString, OpRoot,
LogFile, MailUtil, StrUtil, OproUtil, FileUtil, InterCom, BTree,
Opus_173, MTask, NetFile, Globals, Util, Display;
FUNCTION ReadCostTable(Silent: Boolean): Boolean;
VAR
s : STRING;
CurrentCost:WORD;
f : TBufTextFile;
KeyWord : S20;
Test : Integer;
p : Pointer;
BEGIN
ReadCostTable:=False;
CurrentGeneralCost:=0;
CurrentCostCount:=0;
IF Cfg.NLCompiler.costfilename<>'' THEN
BEGIN
IF NOT Silent THEN
Write('Reading COST Table from "'+JustFileName(cfg.NLCompiler.CostFileName+'". '));
IF f.Init(Cfg.NlCompiler.CostFileName, SOpenRead+ShareDenyW, 2048) THEN
BEGIN
GetMem(p,SizeOf(CostTab));
WHILE NOT f.EoF DO
BEGIN
f.ReadLn(s);
IF Trim(s)<>'' THEN
BEGIN
s:=Trim(StUpCase(s)+' ');
keyword:=nextword(' ',s);
IF Keyword='GENERAL' THEN
BEGIN
keyword:=nextword(' ',s);
Val(keyword,CurrentGeneralCost,test);
IF test<>0 THEN
BEGIN
f.Done;
EXIT;
END;
END ELSE
IF Keyword='COST' THEN
BEGIN
Keyword:=NextWord(' ',s);
Val(keyword,currentcost,test);
IF Test<>0 THEN
BEGIN
f.Done;
EXIT;
END;
END ELSE
BEGIN
Inc(CurrentCostCount);
WITH costtab(p^)[CurrentCostCount] DO
BEGIN
prefix:=KeyWord;
cost:=currentcost;
END;
END;
END;
END;
f.Done;
GetMem(CurrentCostTable,SizeOf(CostType)*CurrentCostCount);
Move(p^,CurrentCostTable^,SizeOf(CostType)*CurrentCostCount);
FreeMem(p,SizeOf(CostTab));
IF NOT Silent THEN WriteLn(CurrentCostCount,' read');
ReadCostTable:=True;
END ELSE
IF NOT Silent THEN
WriteLn('The file containing the Cost Table is missing....');
END;
END;
PROCEDURE ClearCurrentCostTable;
BEGIN
IF CurrentCostTable<>NIL THEN
BEGIN
FreeMemCheck(CurrentCostTable,SizeOf(CostType)*CurrentCostCount);
CurrentCostCount:=0;
END;
END;
FUNCTION FindCost(CONST Phone: S60): Word;
VAR
Prefix : S10;
i : Integer;
p : Pointer;
Cost : Word;
Found : Boolean;
BEGIN
IF CurrentCostCount<>0 THEN
BEGIN
p:=CurrentCostTable;
Cost:=0; i:=0; Found:=False;
REPEAT
Inc(i);
Prefix:=Filter(CostTab(p^)[i].Prefix, ['-']);
IF Prefix=Copy(Filter(Phone, ['-']), 1, Length(Prefix)) THEN
BEGIN
Cost:=CostTab(p^)[i].Cost;
Found:=True;
END;
UNTIL (i=CurrentCostCount) OR Found;
IF NOT Found THEN FindCost:=CurrentGeneralCost ELSE FindCost:=Cost;
END ELSE
FindCost:=0;
END;
PROCEDURE GetSpecialModemInfo(CONST s: STRING; VAR mt: Byte; VAR br: SmallWord);
VAR
i : Byte;
BEGIN
mt:=0;
FOR i:=0 TO 7 DO
IF (Cfg.NLCompiler.MTypeStr[i]<>'') AND (Pos(Cfg.NLCompiler.MTypeStr[i], s)>0) THEN
mt:=mt+(1 SHL i);
FOR i:=0 TO 7 DO
IF (1 SHL Cfg.Modem.ModemType[i].Bit) AND mt<>0 THEN
BEGIN
br:=Cfg.Modem.ModemType[i].Baud;
Break;
END;
END;
PROCEDURE DisposeTranslationTable;
BEGIN
IF TransLationTable<>NIL THEN
BEGIN
FreeMemcHECK(TranslationTable,SizeOf(TNLTranslat)*CurrentTranslatCount);
CurrentTranslatCount:=0;
END;
END;
FUNCTION PhoneTranslation(ph: S60): S60;
VAR
i : Integer;
HaveRead,
InternationalNumber : Boolean;
BEGIN
InternationalNumber:=(Copy(ph,1,Length(Cfg.NLCompiler.OurPrefix))<>Cfg.NLCompiler.ourprefix);
HaveRead:=CurrentTranslatCount=0;
IF HaveRead THEN ReadTranslationTable(True);
FOR i:=1 TO CurrentTranslatCount DO
BEGIN
IF (Copy(ph,1,Length(NLTranslatTab(TranslationTable^)[i].NumFrom))=NLTranslatTab(TranslationTable^)[i].NumFrom) THEN
BEGIN
Delete(ph,1,Length(NLTranslatTab(TranslationTable^)[i].NumFrom));
Insert(NLTranslatTab(TranslationTable^)[i].NumTo,ph,1);
Break;
END;
END;
IF InternationalNumber THEN Insert(Cfg.NLCompiler.IntPrefix,ph,1);
IF HaveRead THEN DisposeTranslationTable;
PhoneTranslation:=ph;
END;
PROCEDURE ReadTranslationTable(Silent: Boolean);
VAR
f : TNetFile;
BEGIN
IF TranslationTable<>NIL THEN DisposeTransLationTable;
CurrentTranslatCount:=0;
IF NOT Silent THEN Write('Reading translation table. ');
IF NOT f.Open(StartPath+PoPNLTranslateFileName,SizeOf(TNLTranslat),False) THEN EXIT;
CurrentTranslatCount:=f.FileSize;
IF CurrentTranslatCount>0 THEN
BEGIN
GetMem(TranslationTable,SizeOf(TNLTranslat)*CurrentTranslatCount);
f.BlockRead(TranslationTable^, CurrentTranslatCount);
END;
f.Close;
IF NOT Silent THEN WriteLn(CurrentTranslatCount,' read.');
END;
FUNCTION CalcNewZone:Integer;
VAR
i:WORD;
idx:NewNodeListIndex;
BEGIN
FOR i:=NodePos DOWNTO 1 DO
BEGIN
NodeListIndex.RetA(i, 0, idx);
IF idx.node=-2 THEN
BEGIN
CalcNewZone:=idx.net;
EXIT;
END;
END;
CalcNewZone:=0;
END;
PROCEDURE DisplaySingleNode(CONST Address: TFidoAddress);
VAR
s,n : S20;
Temp : windowptr;
i : Byte;
BEGIN
WITH nodelistentry DO
BEGIN
n:=Address2Str(Address);
mywin(Temp, 15, 7, 65, 16, 2, 'NodeList Info for ' + n,True);
IF NOT FindNode(Address, NodelistEntry) THEN
BEGIN
FillChar(NodeListEntry,SizeOf(NodeListEntry),0);
SystemName:='Unknown System!!!';
END;
s:='';
FOR i:=0 TO 7 DO
IF (1 SHL Cfg.Modem.ModemType[i].Bit) AND ModemType<>0 THEN
s:=s+', '+Cfg.NlCompiler.MTypeStr[Cfg.Modem.ModemType[i].Bit];
WITH Temp^ DO
BEGIN
wFastText('Node : '+n,2,2);
wFastText('System : '+SystemName,3,2);
wFastText('Sysop : '+SysopName,4,2);
wFastText('Misc. Info : '+MiscInfo,5,2);
wFastText('Phone : '+PhoneNumber,6,2);
wFastText('Max. baud : '+Long2Str(BaudRate)+s,7,2);
END;
WaitForAction(30);
KillWindow(Temp);
END;
END;
FUNCTION GetSysOpName(CONST Adr: TFidoAddress):S40;
VAR
sss,sss2:S60;
s:S40;
nl : NodeListRecType;
tf : TBufTextFile;
BEGIN
s:='SysOp';
IF (Cfg.NodeListTyp<>NewNodeListType) THEN
BEGIN
IF FindNode(Adr,Nl) THEN s:=Nl.SysOpName;
END ELSE
BEGIN
IF tf.Init(Cfg.NodeList+'FIDOUSER.LST', SOpenRead+ShareDenyW, Max64k(MaxAvail-2048)) THEN
BEGIN
sss2:=Address2Str(Adr);
WHILE NOT tf.EOF DO
BEGIN
tf.ReadLn(sss);
IF Copy(sss,61-LENGTH(sss2),LENGTH(sss2))=sss2 THEN
BEGIN
s:=Trim(Copy(sss,1,40));
sss2:=Copy(s,1,POS(',',s)-1);
Delete(s,1,LENGTH(sss2)+1);
WHILE (s<>'') AND (s[1]=' ') DO
Delete(s,1,1);
s:=s+' '+sss2;
Break;
END;
END;
tf.Done;
END;
END;
GetSysOpName:=s;
END;
PROCEDURE DeAllocateNodeListIndex;
BEGIN
IF (Cfg.NodelistTyp<>Version7) And (NodeListPathStr<>'') THEN
BEGIN
NodeListIndex.Done;
NodeListPathStr:='';
DisposeTranslationTable;
ClearCurrentCostTable;
END;
END;
FUNCTION ListExtension(CONST FName: S12): S12;
BEGIN
CASE Cfg.NodelistTyp OF
SBBSNodeListType : ListExtension:=FName+'SBS';
QBBSNodeListType : ListExtension:=FName+'DAT';
RANodeListType : ListExtension:=FName+'RA';
END;
END;
{--------------------------------------------------------------------------}
{ Call this to initialise the nodelist-unit }
{--------------------------------------------------------------------------}
PROCEDURE InitialiseNodelist(CONST NlPath: PathStr; NLType: NodeListType);
VAR
i, j : Word;
NodeListFile : TNetFile;
QBBSNodeListIdx: ARRAY[1..500] OF QBBSNodeIdxRecord;
NewNodeListIdx : ARRAY[1..1250] OF NewNodeListIndex ABSOLUTE QBBSNodeListIdx;
Error : Boolean;
NodeBufferSize : LongInt;
FName : S12;
BEGIN
Error:=False;
IF Cfg.NodelistTyp=Version7 THEN
BEGIN
NodePos:=200000;
Exit;
END;
IF NodeListPathStr=#255 THEN
BEGIN
IF MaxAvail>10240 THEN NodeBufferSize:=MaxAvail-10240 ELSE
BEGIN
NodeBufferSize:=0;
Error:=True;
END;
END ELSE
NodeBufferSize:=MaxAvail-65536;
IF NOT Error THEN
BEGIN
NodeListPathStr:=AddBackSlash(NlPath);
NodeListIndexNum:=0;
OpenLockFile;
REPEAT
GiveUpTime;
UNTIL NetGrabFile(NetNLFile) or KeyPressed;
CASE NLType OF
NewNodelistType : BEGIN
IF NodeListFile.Open(NodeListPathStr+'NODELIST.IDX',SizeOf(NewNodeListIndex), False) THEN
BEGIN
IF NodeListFile.FileSize<65500 THEN
BEGIN
{ NodeListIndex.Init(MakeTaskFileName('PORTAL.NIB'), FileSize(NodeListFile)+100, 4, 65536);}
NodeListIndex.Init(NodeListFile.FileSize+100, 1, 4, MakeTaskFileName(PoPNodelistIdxBuffer),
NodeBufferSize, lDeleteFile, DefaultPriority);
WHILE NOT NodeListFile.EoF DO
BEGIN
NodeListFile.BlockReadNum(NewNodeListIdx, 1250, j);
FOR i:=1 TO j DO
BEGIN
NodeListIndex.SetA(NodeListIndexNum, 0, NewNodeListIdx[i]);
Inc(NodeListIndexNum);
END;
END;
END ELSE
BEGIN
AddLog('!', 'Nodelist file: '+NodeListPathStr+'NODELIST.IDX is too big!');
Error:=True;
END;
NodeListFile.Close;
END ELSE
Error:=True;
END;
QBBSNodelistType,
SBBSNodeListType,
RANodeListType : BEGIN
FName:=ListExtension('NODEIDX.');
IF NodeListFile.Open(NodeListPathStr+FName,SizeOf(QBBSNodeIdxRecord), False) THEN
BEGIN
IF NodeListFile.FileSize<65500 THEN
BEGIN
NodeListIndex.Init(NodeListFile.FileSize, 1, 10, MakeTaskFileName(PoPNodelistIdxBuffer),
NodeBufferSize, lDeleteFile, DefaultPriority);
WHILE NOT NodeListFile.EoF DO
BEGIN
NodeListFile.BlockReadNum(QBBSNodeListIdx, 500, j);
FOR i:=1 TO j DO
BEGIN
NodeListIndex.SetA(NodeListIndexNum, 0, QBBSNodeListIdx[i]);
Inc(NodeListIndexNum);
END;
END;
END ELSE
BEGIN
AddLog('!', 'Nodelist file: '+NodeListPathStr+FName+' is too big!');
Error:=True;
END;
NodeListFile.Close;
END ELSE
Error:=True;
END;
END;
NetReleaseFile(NetNLFile);
CloseLockFile;
END;
IF Error THEN NodeListPathStr:='' ELSE
BEGIN
IF NLType IN [QBBSNodeListType,SBBSNodeListType,RANodeListType] THEN
BEGIN
ReadTranslationTable(True);
ReadCostTable(True);
END;
END;
END;
{--------------------------------------------------------------------------}
{ Remote access Nodelist }
{--------------------------------------------------------------------------}
PROCEDURE ConvRANodeListRec(s: STRING; VAR NodeListRec : NodeListRecType; Zone,Net,Node:Integer);
VAR
KeyWord:S12;
number,Point,test : Integer;
BEGIN
KeyWord:=StUpCase(NextWord(',',s));
Val(NextWord(',',s),Number,test);
Point:=0;
IF (KeyWord='ZONE') THEN
BEGIN
Zone:=Number;
Net:=Number;
Node:=0;
END ELSE
IF (KeyWord='HOST') OR (KeyWord='REGION') THEN
BEGIN
Net:=Number;
Node:=0;
END ELSE
IF KeyWord='POINT' THEN
BEGIN
Point:=Number;
END ELSE
Node:=Number;
FillChar(NodeListRec,SizeOf(NodeListRec),0);
NodeListRec.Adr.Zone:=Zone;
NodeListRec.Adr.Net:=Net;
NodeListRec.Adr.Node:=Node;
NodeListRec.Adr.Point:=Point;
NodeListRec.SystemName:=NextWord(',',s);
Replace(NodeListRec.SystemName,'_',' ',0);
NodeListRec.MiscInfo:=NextWord(',',s);
Replace(NodeListRec.MiscInfo,'_',' ',0);
NodeListRec.SysopName:=NextWord(',',s);
Replace(NodeListRec.SysOpName,'_',' ',0);
NodeListRec.PhoneNumber:=NextWord(',',s);
NodeListRec.Cost:=FindCost(NodeListRec.PhoneNumber);
NodeListRec.RealCost:=NodeListRec.Cost;
IF NOT IsOurAddress(NodelistRec.Adr) THEN
NodeListRec.PhoneNumber:=PhoneTranslation(NodeListRec.PhoneNumber);
Val(NextWord(',',s),NodeListRec.BaudRate,Test);
GetSpecialModemInfo(StUpCase(s),NodeListRec.ModemType,NodeListRec.BaudRate);
s:=s+',';
WHILE s<>'' DO
BEGIN
KeyWord:=NextWord(',',s);
IF KeyWord='CM' THEN NodeListRec.Flags:=NodeListRec.Flags OR nlf_CrashMail;
END;
END;
{--------------------------------------------------------------------------}
{ Version 6 Nodelist }
{--------------------------------------------------------------------------}
PROCEDURE ConvNewNodelistRec(NodelistRecZ: NewNodeList; VAR NodelistRec: NodeListRecType; RealZone : Integer);
BEGIN
WITH NodelistRec DO
BEGIN
Adr.Zone:=RealZone;
Adr.Net:=NodelistRecZ.NetNumber;
Adr.Node:=NodelistRecZ.NodeNumber;
Cost:=NodelistRecZ.Cost;
SystemName:=Asciiz2Str(NodelistRecZ.SystemName, 34);
PhoneNumber:=Asciiz2Str(NodelistRecZ.PhoneNumber, 40);
MiscInfo:=Asciiz2Str(NodelistRecZ.MiscInfo, 30);
Password:=Asciiz2Str(NodelistRecZ.Password, 8);
RealCost:=NodelistRecZ.RealCost;
BaudRate:=NodelistRecZ.BaudRate * 300;
ModemType:=NodelistRecZ.ModemType;
Flags:=NodelistRecZ.NodeFlags;
HubNode:=NodelistRecZ.HubNode;
IF (Flags AND nlf_HubNode)<>0 THEN
BEGIN
Adr.Point:=HubNode;
HubNode:=0;
END;
END;
END;
PROCEDURE ReConvNewNodelistRec(VAR NodelistRecZ: NewNodeList; CONST NodelistRec: NodeListRecType);
BEGIN
WITH NodelistRec DO
BEGIN
NodelistRecZ.NetNumber:=Adr.Net;
NodelistRecZ.NodeNumber:=Adr.Node;
NodelistRecZ.Cost:=Cost;
Str2AsciiZ(SystemName, NodelistRecZ.SystemName,34);
Str2AsciiZ(PhoneNumber, NodelistRecZ.PhoneNumber,40);
Str2AsciiZ(MiscInfo, NodelistRecZ.MiscInfo,30);
Str2AsciiZ(Password, NodelistRecZ.Password,8);
NodelistRecZ.RealCost:=RealCost;
IF Adr.Point=0 THEN
NodelistRecZ.HubNode:=HubNode
ELSE
BEGIN
NodelistRecZ.HubNode:=Adr.Point;
NodelistRecZ.NodeFlags:=NodelistRecZ.NodeFlags OR nlf_HubNode; {???}
END;
NodelistRecZ.BaudRate:=BaudRate DIV 300;
NodelistRecZ.ModemType:=ModemType;
NodelistRecZ.NodeFlags:=Flags;
END;
END;
FUNCTION GetNewNodelistInfo(RecNo: LongInt; VAR NListRec: NewNodeList): Boolean;
VAR
NodeList : TNetFile;
BEGIN
GetNewNodelistInfo:=False;
IF Nodelist.Open(NodeListPathStr+'NODELIST.DAT', SizeOf(NewNodelist), False) THEN
BEGIN
Nodelist.GetRec(NListRec,RecNo,NoKeep,Wait);
GetNewNodelistInfo:=(Nodelist.IoResult=0);
NodeList.Close;
END;
END;
FUNCTION SaveNewNodelistInfo(RecNo : LongInt; VAR NListRec : NewNodeList) : Boolean;
VAR
NodeList, NodeListIdx : TNetFile;
NListIdxRec : NewNodeListIndex;
BEGIN
SaveNewNodelistInfo:=True;
Nodelist.Open(NodeListPathStr+'NODELIST.DAT',SizeOf(NewNodeList),False);
Nodelist.PutRec(NListRec, RecNo);
IF Nodelist.IoResult=0 THEN
BEGIN
Nodelist.Close;
WITH NListRec DO
BEGIN
IF (NodeFlags AND nlf_HubNode)=0 THEN
BEGIN
NListIdxRec.Net:=NetNumber;
NListIdxRec.Node:=NodeNumber;
END ELSE
BEGIN
NListIdxRec.Net:=-1;
NListIdxRec.Node:=HubNode;
END;
END;
NodeListIdx.Open(NodeListPathStr+'NODELIST.IDX',SizeOf(NewNodeListIndex),False);
NodeListIdx.PutRec(NListIdxRec, RecNo);
NodeListIdx.Close;
END ELSE
SaveNewNodelistInfo:=False;
END;
FUNCTION GetV7Info(RecNo: LongInt; VAR NlRec: NodelistRecType): Boolean;
VAR
s : String;
V7 : Version7NlType;
f : TNetFile;
BEGIN
FillChar(NlRec,SizeOf(NlRec),0);
GetV7Info:=True;
f.Open(Cfg.Nodelist+'NODEX.DAT',1,False);
f.Seek(RecNo);
f.BlockRead(V7,SizeOf(Version7NlType));
f.BlockRead(NlRec.PhoneNumber[1],V7.Phone_Len); NlRec.PhoneNumber[0]:=Char(V7.Phone_Len);
f.BlockRead(NlRec.Password[1],V7.Password_Len); NlRec.Password[0]:=Char(V7.Password_Len);
f.BlockRead(s[1],V7.Pack_Len); s[0]:=Char(V7.Pack_Len);
f.Close;
s:=unpack(s);
WITH NlRec DO
BEGIN
Adr.Zone:=V7.Zone;
Adr.Net:=V7.Net;
Adr.Node:=V7.Node;
Cost:=V7.CallCost;
SystemName:=FancyStr(Copy(s,1,V7.BName_Len));
MiscInfo:=FancyStr(Copy(s,V7.BName_Len+V7.SName_Len+1,V7.CName_Len));
SysopName:=FancyStr(Copy(s,V7.BName_Len+1,V7.SName_Len));
RealCost:=V7.CallCost;
HubNode:=V7.HubNode;
BaudRate:=V7.BaudRate*300;
ModemType:=V7.ModemType;
Flags:=V7.NodeFlags;
IF (Flags AND nlf_HubNode)<>0 THEN
BEGIN
Adr.Point:=HubNode;
HubNode:=0;
END;
END;
END;
FUNCTION FindNode(CONST Address: TFidoAddress; VAR NlistRecZ : NodeListRecType) : Boolean;
VAR
ew,KeyWord: S6;
s : STRING;
buf : ARRAY[1..10] OF CHAR;
Found : Boolean;
i : LongInt;
NewIdx : NewNodelistIndex ABSOLUTE buf;
QI : QBBSNodeIdxRecord ABSOLUTE buf;
NListRec : NewNodeList;
Rf : FILE OF NodeExtra;
rx : NodeExtra;
tf : TBufTextFile;
add : Byte;
b,
CurZone : Integer;
FName : S12;
PROCEDURE FindRawNode(NP:WORD);
VAR
NextOffSet : LongInt;
ss : STRING;
IORes : Integer;
BEGIN
Found:=False;
FName:=ListExtension('NODEINC.');
Assign(rf,NodeListPathStr+FName);
FileMode:=ShareRead+ShareDenyNone;
RESET(rf);
IF IOResult=0 THEN
BEGIN
Seek(rf,QI.RawFile-1);
IORes:=IOResult;
IF IORes=0 THEN READ(rf,rx);
IORes:=IOResult;
CurrentTextFileNumber:=QI.RawFile;
Close(rf);
IF (IoRes=0) AND tf.Init(NodeListPathStr+rx.name, SOpenRead+ShareDenyNone, Max64k(10240)) THEN
BEGIN
tf.Seek(QI.RawPos);
IF IOResult=0 THEN
BEGIN
tf.ReadLn(s);
ss:=StUpCase(Copy(s,1,4));
IF (Address.Node=0) AND
(((ss='ZONE') AND (Address.Net=Address.Net)) OR
(((ss='HOST') OR (ss='REGI')) AND (Address.Node=0))) THEN
BEGIN
Found:=True;
NodePos:=tf.GetPos-Length(s)-2;
END ELSE
BEGIN
IF NP<NodeListIndexNum-2 THEN
BEGIN
NodeListIndex.RetA(NP+1, 0, buf);
CASE Cfg.NodeListTyp OF
RaNodeListType,
SBBSNodeListType,
QBBSNodeListType : BEGIN
IF QI.RawFile=CurrentTextFileNumber THEN
NextOffSet:=QI.RawPos
ELSE
NextOffSet:=$7FFFFFFF;
END;
END;
END ELSE
NextOffSet:=tf.GetSize+1;
IF NextOffSet=0 THEN NextOffSet:=tf.GetSize+1;
Found:=False;
KeyWord:='HOST';
ew:='';
WHILE NOT tf.EOF AND NOT Found AND (NextOffset>tf.GetPos) DO
BEGIN
tf.ReadLn(s);
IF Copy(s,1,1)<>';' THEN
BEGIN
IF (s<>'') AND (s[1]<>',') THEN add:=1 ELSE add:=0;
KeyWord:=StUpCase(ExtractWord(add,s,[',']));
ew:=ExtractWord(1+add,s,[',']);
IF (KeyWord<>'POINT') AND
((ew=Long2Str(Address.Node)) OR ((ss='ZONE') AND (ew=Long2Str(Address.Net)))) THEN
BEGIN
IF (Address.Point=0) AND (KeyWord<>'POINT') THEN
BEGIN
Found:=True;
NodePos:=tf.GetPos-Length(s)-2;
END ELSE
BEGIN
IF (Address.Node=0) AND (ew<>'0') AND (ss<>'ZONE') THEN
BEGIN
Break;
END;
ew:='';
KeyWord:='POINT';
WHILE NOT tf.EOF AND NOT Found AND (NextOffset>tf.GetPos) AND
(KeyWord='POINT') AND (ew<>Long2Str(Address.Point)) DO
BEGIN
tf.ReadLn(s);
IF Copy(s,1,1)<>';' THEN
BEGIN
IF (s<>'') AND (s[1]<>',') THEN add:=1 ELSE add:=0;
KeyWord:=StUpCase(ExtractWord(add,s,[',']));
ew:=ExtractWord(1+add,s,[',']);
IF (KeyWord='POINT') AND (ew=Long2Str(Address.Point)) THEN
BEGIN
Found:=True;
NodePos:=tf.GetPos-Length(s)-2;
END;
END;
END;
IF NOT Found THEN NextOffSet:=-1;
END;
END;
END;
END;
END;
END;
tf.Done;
END;
END;
END;
BEGIN
FindNode:=False;
FillChar(NlistRecZ, SizeOf(NListRecZ), 0);
IF Cfg.NodelistTyp=Version7 THEN
BEGIN
Found:=FindKey(Cfg.Nodelist+'NODEX.NDX',i,Address2Opus(Address));
END ELSE
BEGIN
IF CheckICToDo(ICTDReReadNLIdx) THEN
BEGIN
DeAllocateNodeListIndex;
InitialiseNodeList(Cfg.NodeList,Cfg.NodeListTyp);
END;
Found:=False;
IF NodeListIndexNum=0 THEN EXIT;
i:=-1; CurZone:=0;
REPEAT
REPEAT
Inc(i);
NodeListIndex.RetA(i, 0, buf);
WITH Address DO
CASE Cfg.NodeListTyp OF
NewNodeListType : BEGIN
IF NewIdx.Node=-2 THEN CurZone:=NewIdx.Net;
IF NewIdx.Node<0 THEN NewIdx.Node:=0;
Found:=((Zone=CurZone) And (Net=NewIdx.Net) And (Node=NewIdx.Node));
END;
RANodeListType,
SBBSNodelistType,
QBBSNodeListType : BEGIN
IF (QI.NodeType=ntZone) THEN
BEGIN
CurZone:=QI.Number;
{QI.Number:=0;}
END;
Found:=(CurZone=Zone) AND ((QI.Number=Net) OR (Net=0));
IF Found THEN FindRawNode(i);
END;
END;
UNTIL Found OR (i>=NodeListIndexNum-1);
IF Found And (Address.Point<>0) THEN
BEGIN
CASE Cfg.NodeListTyp OF
NewNodeListType : BEGIN
Found:=False;
REPEAT
Inc(i);
NodeListIndex.RetA(i, 0, buf);
IF Cfg.NodeListTyp=NewNodeListType THEN
Found:=((NewIdx.Net=-1) And (Address.Point=NewIdx.Node));
UNTIL Found OR (i=NodeListIndexNum-1) OR
(NewIdx.Net<>-1);
END;
RANodeListType,
QBBSNodeListType,
SBBSNodeListType: BEGIN
ConvRANodeListRec(s,NListRecZ,Address.Zone,Address.Net,Address.Node);
END;
END;
END;
UNTIL Found Or (i>=NodeListIndexNum-1);
END;
IF Found THEN
BEGIN
FindNode:=True;
CASE Cfg.NodeListTyp OF
Version7 : BEGIN
IF Not GetV7Info(i,NListRecZ) THEN FindNode:=False;
END;
NewNodelistType : BEGIN
NodePos:=i;
IF GetNewNodelistInfo(i, NListRec) THEN
ConvNewNodelistRec(NListRec, NlistRecZ, Address.Zone)
ELSE
FindNode:=False;
END;
QBBSNodelistType,
SBBSNodelistType,
RANodeListType : BEGIN
ConvRANodeListRec(s,NListRecZ,Address.Zone,Address.Net,Address.Node);
END;
END;
b:=0;
FOR i:=0 TO 7 DO
IF (1 SHL Cfg.Modem.ModemType[i].Bit) AND NListRecZ.ModemType<>0 THEN
BEGIN
b:=Cfg.Modem.ModemType[i].Baud;
Break;
END;
IF b<>0 THEN NListRecZ.BaudRate:=b;
END;
END;
FUNCTION WriteNode(CONST NListRec : NodeListRecType) : Boolean;
VAR
NlistRecZ : NewNodeList;
vi : VirtualIndexType;
BEGIN
WriteNode:=True;
IF Cfg.NodelistTyp=NewNodelistType THEN
BEGIN
IF NListRec.Adr.Point=0 THEN
BEGIN
vi.zone:=NListRec.Adr.Net;
vi.net:=NListRec.Adr.Node;
END
ELSE
BEGIN
vi.Zone:=NListRec.Adr.Point;
vi.Net:=-1;
END;
END ELSE
BEGIN
vi.zone:=NListRec.Adr.Zone;
vi.net:=NListRec.Adr.Net;
vi.node:=NListRec.Adr.Node;
END;
NodeListIndex.SetA(NodePos, 0, vi);
CASE Cfg.NodeListTyp OF
NewNodelistType : BEGIN
ReConvNewNodelistRec(NlistRecZ, NListRec);
IF NOT SaveNewNodelistInfo(NodePos, NlistRecZ) THEN WriteNode:=False;
END;
END;
END;
FUNCTION FindFirstNode(VAR NListRec : NodeListRecType) : Boolean;
VAR
NlistRecZ : NewNodeList;
Qn : QBBSNodeIdxRecord;
TmpAdr : TFidoAddress;
BEGIN
FindFirstNode:=True;
NodePos:=0;
FillChar(NListRec, SizeOf(NListRec), 0);
CASE Cfg.NodeListTyp OF
NewNodelistType : BEGIN
IF GetNewNodelistInfo(NodePos, NlistRecZ) THEN
ConvNewNodelistRec(NlistRecZ, NListRec, CalcNewZone) ELSE FindFirstNode:=False;
END;
QBBSNodelistType,
SBBSNodelistType,
RANodeListType : BEGIN
NodeListIndex.RetA(0, 0, Qn);
TmpAdr.Zone:=Qn.Number;
TmpAdr.Net:=0;
TmpAdr.Node:=0;
TmpAdr.Point:=0;
FindFirstNode:=FindNode(TmpAdr,NListRec);
END;
END;
END;
FUNCTION FindNextNode(VAR NListRec : NodeListRecType) : Boolean;
LABEL
RAAgain;
VAR
KeyWord : S12;
s : STRING;
NlistRecZ : NewNodeList;
Rf : TNetFile;
tf : TBufTextFile;
rx : NodeExtra;
add : Byte;
test : Integer;
Number : Integer;
Done : Boolean;
TmpAdr : TFidoAddress;
FName : S12;
RecNum : LONGINT;
BEGIN
FindNextNode:=True;
TmpAdr:=NListRec.Adr;
FillChar(NListRec, SizeOf(NListRec), 0);
Inc(NodePos);
CASE Cfg.NodeListTyp OF
NewNodelistType : BEGIN
IF GetNewNodelistInfo(NodePos, NlistRecZ) THEN
ConvNewNodelistRec(NlistRecZ, NListRec, CalcNewZone)
ELSE
BEGIN
Dec(NodePos);
FindNextNode:=False;
END;
END;
Version7 : BEGIN
IF NextKey(Cfg.Nodelist+'NODEX.NDX',RecNum,Address2Opus(TmpAdr)) THEN
FindNextNode:=GetV7Info(REcNum,NListRec);
END;
QBBSNodelistType,
SBBSNodelistType,
RANodeListType : BEGIN
Dec(NodePos);
RAAgain:
FName:=ListExtension('NODEINC.');
IF rf.Open(NodeListPathStr+FName,SizeOf(NodeExtra),False) THEN
BEGIN
rf.GetRec(rx,CurrentTextFileNumber-1,NoKeep,Wait);
rf.Close;
IF tf.Init(NodeListPathStr+rx.name, SOpenRead+ShareDenyNone, 10240) THEN
BEGIN
tf.SetPos(NodePos, PosAbs);
IF tf.GetStatus=0 THEN
BEGIN
tf.ReadLn(s); (* Læs nuv. node *)
Done:=False;
WHILE NOT tf.EOF AND NOT Done DO
BEGIN
tf.ReadLn(s);
IF (s<>'') AND (s[1]<>';') THEN Done:=True;
END;
tf.Done;
IF Not Done THEN
BEGIN
Inc(CurrentTextFileNumber);
NodePos:=0;
GOTO RAAgain;
END;
IF Done THEN
BEGIN
IF s[1]<>',' THEN add:=1 ELSE add:=0;
KeyWord:=ExtractWord(1+add,s,[',']);
Val(KeyWord,Number,Test);
KeyWord:=StUpCase(ExtractWord(add,s,[',']));
IF (KeyWord='ZONE') THEN
BEGIN
TmpAdr.Zone:=Number;
TmpAdr.Net :=Number;
TmpAdr.Node:=0;
TmpAdr.Point:=0;
END ELSE
IF (KeyWord='HOST') OR (KeyWord='REGION') THEN
BEGIN
TmpAdr.Net:=Number;
TmpAdr.Node:=0;
TmpAdr.Point:=0;
END ELSE
IF (KeyWord='POINT') THEN
BEGIN
TmpAdr.Point:=Number;
END ELSE
TmpAdr.Node:=Number;
IF FindNode(TmpAdr,NListRec) THEN FindNextNode:=True;
END ELSE
FindNextNode:=False;
END;
END;
END ELSE
FindNextNode:=False;
END;
END;
END;
FUNCTION FindPreviousNode(VAR NListRec : NodeListRecType) : Boolean;
LABEL
RAAgain;
VAR
NlistRecZ : NewNodeList;
QIdx : QBBSNodeIdxRecord;
Rf, tf : TNetFile;
rx : NodeExtra;
add,ifn : Byte;
OurNet,
OurZone,
test,i,
Number : Integer;
TmpAdr : TFidoAddress;
Done : Boolean;
s : STRING;
FName,
KeyWord : S12;
RecNum,io, tfpos : LongInt;
BEGIN
FindPreviousNode:=True;
TmpAdr:=NListRec.Adr;
FillChar(NListRec, SizeOf(NListRec), 0);
Dec(NodePos);
IF NodePos < 0 THEN
BEGIN
FindPreviousNode:=False;
NodePos:=0;
END ELSE
BEGIN
CASE Cfg.NodeListTyp OF
NewNodelistType : BEGIN
IF GetNewNodelistInfo(NodePos, NlistRecZ) THEN
ConvNewNodelistRec(NlistRecZ, NListRec, CalcNewZone) ELSE FindPreviousNode:=False;
END;
Version7 : BEGIN
IF PrevKey(Cfg.Nodelist+'NODEX.NDX',RecNum,Address2Opus(TmpAdr)) THEN
FindPreviousNode:=GetV7Info(RecNum,NListRec);
END;
QBBSNodelistType,
SBBSNodelistType,
RANodeListType : BEGIN
Inc(NodePos);
RAAgain:
FName:=ListExtension('NODEINC.');
IF rf.Open(NodeListPathStr+FName,SizeOf(NodeExtra),False) THEN
BEGIN
rf.GetRec(rx,CurrentTextFileNumber-1,NoKeep,Wait);
rf.Close;
IF tf.Open(NodeListPathStr+rx.name,1,False) THEN
BEGIN
IF NodePos=-2 THEN NodePos:=tf.FileSize;
tf.Seek(NodePos);
IF tf.IOResult=0 THEN
BEGIN
Done:=False;
WHILE (tf.FilePos>0) AND NOT Done DO
BEGIN
tf.ReadLineBack(s);
IF (s<>'') AND (s[1]<>';') THEN Done:=True;
END;
tfpos:=tf.FilePos;
tf.Close;
IF Not Done THEN
BEGIN
NodePos:=-2;
Dec(CurrentTextFileNumber);
GOTO RAAgain;
END;
IF Done THEN
BEGIN
IF s[1]<>',' THEN add:=1 ELSE add:=0;
KeyWord:=ExtractWord(1+add,s,[',']);
Val(KeyWord,Number,Test);
KeyWord:=StUpCase(ExtractWord(add,s,[',']));
IF (KeyWord='ZONE') THEN
BEGIN
TmpAdr.Zone:=Number;
TmpAdr.Net :=Number;
TmpAdr.Node:=0;
TmpAdr.Point:=0;
END ELSE
IF (KeyWord='HOST') OR (KeyWord='REGION') THEN
BEGIN
TmpAdr.Net:=Number;
TmpAdr.Node:=0;
TmpAdr.Point:=0;
END ELSE
IF (KeyWord='POINT') THEN
BEGIN
TmpAdr.Point:=Number;
END ELSE
BEGIN
TmpAdr.Node:=Number;
Done:=False;
Ifn:=0;
i:=-1;
WHILE NOT Done AND (i<NodelistIndexNum-1) AND (ifn<=CurrentTextFileNumber) DO
BEGIN
Inc(i);
NodeListIndex.RetA(i,0,QIdx);
CASE Cfg.NodeListTyp OF
RANodeListType,
SBBSNodeListType,
QBBSNodeListType : BEGIN
WITH QIdx DO
BEGIN
OurZone:=TmpAdr.Zone;
OurNet:=TmpAdr.Net;
ifn:=RawFile;
io:=RawPos;
IF ifn>CurrentTextFileNumber THEN Break;
IF (NodeType=ntZone) THEN TmpAdr.Zone:=Number ELSE
IF (NodeType=ntRegion) OR (NodeType=ntNet) THEN TmpAdr.Net:=Number;
END;
END;
END;
IF ((ifn=CurrentTextFileNumber) AND (io>tfpos)) OR (i=NodeListIndexNum-2) THEN
BEGIN
Done:=True;
TmpAdr.Zone:=OurZone;
TmpAdr.Net:=OurNet;
END;
END;
END;
NodePos:=TfPos;
ConvRaNodeListRec(s,NListRec,TmpAdr.Zone,TmpAdr.Net,TmpAdr.Node);
FindPreviousNode:=True;
END ELSE
FindPreviousNode:=False;
END;
END;
END;
END;
END;
END;
END;
END.